/*
{
    "coord":{
        "lon":116.39,
        "lat":39.91
    },
    "weather":[
        {
            "id":501,
            "main":"Rain",
            "description":"moderate rain",
            "icon":"10d"
        },
        {
            "id":701,
            "main":"Mist",
            "description":"mist",
            "icon":"50d"
        }
    ],
    "base":"stations",
    "main":{
        "temp":24.24,
        "pressure":1008,
        "humidity":88,
        "temp_min":22,
        "temp_max":26.11
    },
    "visibility":5000,
    "wind":{
        "speed":2,
        "deg":200
    },
    "rain":{
        "1h":1.52
    },
    "clouds":{
        "all":90
    },
    "dt":1566271028,
    "sys":{
        "type":1,
        "id":9609,
        "message":0.0072,
        "country":"CN",
        "sunrise":1566250223,
        "sunset":1566299158
    },
    "timezone":28800,
    "id":1816670,
    "name":"Beijing",
    "cod":200
}
*/
#include "weather.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include "ArduinoJson.h"
#include "GxEPD2_BW.h"
// time
#include <time.h>                       // time() ctime()
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#include "freertos/queue.h"
#include "struct_def.h"

extern GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> eink ;
extern QueueHandle_t g_event_queue_handle ;
extern EventGroupHandle_t g_sync_event_group;

//https://openweathermap.org
static const String key = "26adb3d2c8880174ba4ac70d0a1c8906";
static const String endpoint_current =  "http://api.openweathermap.org/data/2.5/weather?q=Beijing,cn&units=metric&APPID=";
static const String endpoint_forecast = "http://api.openweathermap.org/data/2.5/forecast?q=Beijing,cn&units=metric&appid=" ;
 
 
LV_IMG_DECLARE(icon64_01d);
LV_IMG_DECLARE(icon64_01n);
LV_IMG_DECLARE(icon64_02d);
LV_IMG_DECLARE(icon64_02n);
LV_IMG_DECLARE(icon64_03d);
LV_IMG_DECLARE(icon64_04d);
LV_IMG_DECLARE(icon64_09d);
LV_IMG_DECLARE(icon64_10d);
LV_IMG_DECLARE(icon64_11d);
LV_IMG_DECLARE(icon64_13d);
LV_IMG_DECLARE(icon64_50d);
LV_IMG_DECLARE(icon64_50n);

LV_IMG_DECLARE(icon128_01d);
LV_IMG_DECLARE(icon128_01n);
LV_IMG_DECLARE(icon128_02d);
LV_IMG_DECLARE(icon128_02n);
LV_IMG_DECLARE(icon128_03d);
LV_IMG_DECLARE(icon128_04d);
LV_IMG_DECLARE(icon128_09d);
LV_IMG_DECLARE(icon128_10d);
LV_IMG_DECLARE(icon128_11d);
LV_IMG_DECLARE(icon128_13d);
LV_IMG_DECLARE(icon128_50d);
LV_IMG_DECLARE(icon128_50n);



static IconIdPair IconIds[] = {
	{"01d", &icon64_01d, NULL, &icon128_01d, NULL, NULL},
	{"01n", &icon64_01n, NULL, &icon128_01n, NULL, NULL},
	{"02d", &icon64_02d, NULL, &icon128_02d, NULL, NULL},
	{"02n", &icon64_02n, NULL, &icon128_02n, NULL, NULL},
	{"03d", &icon64_03d, NULL, &icon128_03d, NULL, NULL},
	{"03n", &icon64_03d, NULL, &icon128_03d, NULL, NULL},
	{"04d", &icon64_04d, NULL, &icon128_04d, NULL, NULL},
	{"04n", &icon64_04d, NULL, &icon128_04d, NULL, NULL},
	{"09d", &icon64_09d, NULL, &icon128_09d, NULL, NULL},
	{"09n", &icon64_09d, NULL, &icon128_09d, NULL, NULL},
	{"10d", &icon64_10d, NULL, &icon128_10d, NULL, NULL},
	{"10n", &icon64_10d, NULL, &icon128_10d, NULL, NULL},
	{"11d", &icon64_11d, NULL, &icon128_11d, NULL, NULL},
	{"11n", &icon64_11d, NULL, &icon128_11d, NULL, NULL},
	{"13d", &icon64_13d, NULL, &icon128_13d, NULL, NULL},
	{"13n", &icon64_13d, NULL, &icon128_13d, NULL, NULL},
	{"50d", &icon64_50d, NULL, &icon128_50d, NULL, NULL},
	{"50n", &icon64_50n, NULL, &icon128_50n, NULL, NULL},
};




static void btn_back_event_cb(lv_obj_t * btn, lv_event_t event);
const void *iconIdToImage(const char *id, int size);  
static void vTimerCallback(xTimerHandle pxTimer); 

HTTPClient http;
 
static   lv_obj_t *scr;
static   lv_obj_t *img ;                        
static   lv_obj_t *label_temper ;
static   lv_obj_t *label_name ;  
static   lv_obj_t *label_main ;      
static   lv_obj_t *label_humidity ;
static   lv_obj_t *label_minmax  ;
static   lv_obj_t *label_time ;  
static   lv_obj_t *btn_back ;
static   lv_obj_t *btn_refresh;
static   lv_obj_t *label_back ;
static   lv_obj_t *label_refresh ; 


Weather_cur weather_cur;
// Weather_Forecast weather_forecast[40];
// weather_indoor_t weather_indoor;;


static int32_t sync_cnt=0;
static TimerHandle_t timerhandle_weather = NULL;

 


void weather_create(lv_obj_t *obj, lv_event_t event)
{
    if(event==LV_EVENT_CLICKED)
    {
        //EINK

        eink.setTextColor(GxEPD_BLACK);
        eink.setFullWindow();
        eink.fillScreen(GxEPD_WHITE);       
        eink.display(false);
        // delay(3000);

        scr = lv_obj_create(scr_eink,NULL);
        lv_obj_set_size(scr,176,264);
        img = lv_img_create(scr,NULL);                        
        label_temper = lv_label_create(scr, NULL);
        label_name = lv_label_create(scr, NULL);  
        label_main = lv_label_create(scr, NULL);      
        label_humidity = lv_label_create(scr, NULL);
        label_minmax = lv_label_create(scr, NULL);
        label_time = lv_label_create(scr, NULL);

         

        btn_back = lv_btn_create(scr,NULL);
        lv_obj_set_size(btn_back,40,40);
        static lv_style_t style_btn;
        lv_style_copy(&style_btn,&lv_style_transp);
        lv_btn_set_style(btn_back,LV_BTN_STYLE_REL,&style_btn);
        lv_btn_set_style(btn_back,LV_BTN_STYLE_PR,&style_btn);

        btn_refresh = lv_btn_create(scr,btn_back);
        label_back = lv_label_create(btn_back,NULL);
        label_refresh = lv_label_create(btn_refresh,NULL);

        lv_label_set_text(label_back,LV_SYMBOL_CLOSE); 
        lv_label_set_text(label_refresh,LV_SYMBOL_REFRESH); 

        lv_obj_align(btn_back,scr,LV_ALIGN_IN_TOP_LEFT,0,0);lv_obj_set_event_cb(btn_back, btn_back_event_cb);
        lv_obj_align(btn_refresh,scr,LV_ALIGN_IN_TOP_RIGHT,0,0);     
        


        static lv_style_t style_big,style_mid,style_little;
        lv_style_copy(&style_big,&lv_style_plain);
        style_big.text.font = &lv_font_roboto_28;

        lv_style_copy(&style_mid,&lv_style_plain);
        style_mid.text.font = &lv_font_roboto_16;

        lv_style_copy(&style_little,&lv_style_plain);
        style_little.text.font = &lv_font_unscii_8;
        lv_label_set_style(label_temper,LV_LABEL_STYLE_MAIN,&style_big);
        lv_label_set_style(label_main,LV_LABEL_STYLE_MAIN,&style_mid);
        lv_label_set_style(label_name,LV_LABEL_STYLE_MAIN,&style_mid);
        lv_label_set_style(label_humidity,LV_LABEL_STYLE_MAIN,&style_mid); 
        lv_label_set_style(label_minmax,LV_LABEL_STYLE_MAIN,&style_little);
        lv_label_set_style(label_time,LV_LABEL_STYLE_MAIN,&style_little);   
        lv_label_set_style(label_back,LV_LABEL_STYLE_MAIN,&style_mid);  
        lv_label_set_style(label_refresh,LV_LABEL_STYLE_MAIN,&style_mid);  

        //TFT
        lv_label_set_text(label_menu,"weather");
        lv_obj_align(label_menu,scr_tft,LV_ALIGN_CENTER,0,0);
 

        eink_flash_ready=false;
        eink_scene_ready=false;
 
        task_event_data_t event_data;
  
        event_data.type = MSG_WIFI;
        event_data.wifi.event = WIFI_CONFIG_TRY_CONNECT;
        xQueueSend(g_event_queue_handle,&event_data, portMAX_DELAY);

    //创建定时器,once
          timerhandle_weather = xTimerCreate(
                  "weaher timer",
                  pdMS_TO_TICKS(1000*30),
                  pdTRUE,
                  0,
                  vTimerCallback);
          xTimerStart(timerhandle_weather,0);     
    
    }    

}





void weather_sync(void *data)
{
    
    int httpCode;
    DeserializationError error;
    
    StaticJsonDocument<1408> doc;
    HTTPClient http;
    String payload ;
     
    // DynamicJsonDocument doc_frecast(40*1024);
    // http.begin(endpoint_forecast + key); //Specify the URL
    // httpCode = http.GET();  //Make the request
    // if (httpCode ==200) 
    // { //Check for the returning code
    
    //         payload = http.getString();
    //         Serial.println(payload.length());
    //         Serial.println(httpCode);
    //         // Serial.println(payload);
    //             // Deserialize the JSON document
    //         error = deserializeJson(doc_frecast, payload.c_str());
    //         if (error) 
    //         {
    //                 Serial.print(F("deserializeJson() failed: "));
    //                 Serial.println(error.c_str());
            
    //         }
    //         else
    //         {       uint8_t cnt = doc_frecast["cnt"];
    //                 for(uint8_t i=0;i<2;i++)
    //                 {       String datetime = doc_frecast["list"][i]["dt_txt"];
    //                         String condition = doc_frecast["list"][i]["weather"][0]["description"];
    //                         Serial.print(datetime);Serial.println(condition);
    //                 }
                    
    //         }
    // }
    // else 
    // {
    //     Serial.println("Error on HTTP request");
    // }
    // http.end();

    http.begin(endpoint_current + key); //Specify the URL
    httpCode = http.GET();  //Make the request

    if (httpCode ==200) 
    { //Check for the returning code

        payload = http.getString();
        // Serial.println(payload.length());
        // Serial.println(httpCode);
        // Serial.println(payload);
        
            // Deserialize the JSON document
        error = deserializeJson(doc, payload.c_str());

        // Test if parsing succeeds.
        if (error) 
        {
            Serial.print(F("deserializeJson() failed: "));
            Serial.println(error.c_str());
                
        }
        else
        {       
                weather_cur.coord_lon = doc["coord"]["lon"];//City geo location, longitude
                weather_cur.coord_lat = doc["coord"]["lat"];//City geo location, latitude

                weather_cur.weather_id0 = doc["weather"][0]["id"];// Weather condition id
                weather_cur.weather_main0 = doc["weather"][0]["main"];//Group of weather parameters (Rain, Snow, Extreme etc.)
                weather_cur.weather_description0 = doc["weather"][0]["description"];//Weather condition within the group
                weather_cur.weather_icon0 = doc["weather"][0]["icon"];// Weather icon id
                

                
                weather_cur.weather_id1 = doc["weather"][0]["id"];// Weather condition id
                weather_cur.weather_main1 = doc["weather"][0]["main"];//Group of weather parameters (Rain, Snow, Extreme etc.)
                weather_cur.weather_description1 = doc["weather"][0]["description"];//Weather condition within the group
                weather_cur.weather_icon1 = doc["weather"][0]["icon"];// Weather icon id
                
                //
                weather_cur.main_temp = doc["main"]["temp"];//温度。单位默认值：开尔文，公制：摄氏度，英制：华氏度。
                weather_cur.main_pressure = doc["main"]["pressure"];//大气压力（在海平面，如果没有sea_level或grnd_level数据），hPa
                weather_cur.main_humidity = doc["main"]["humidity"];//湿度，％
                weather_cur.main_temp_min = doc["main"]["temp_min"];//目前的最低温度。这是大城市和地理位置扩展的特大城市可能的当前温度的偏差（可选地使用这些参数）。单位默认值：开尔文，公制：摄氏度，英制：华氏度。
                weather_cur.main_temp_max = doc["main"]["temp_max"];//目前的最高温度。这是大城市和地理位置扩展的特大城市可能的当前温度的偏差（可选地使用这些参数）。单位默认值：开尔文，公制：摄氏度，英制：华氏度。
                weather_cur.dt = doc["dt"];
                weather_cur.timezone = doc["timezone"]; 
                weather_cur.dt+=weather_cur.timezone;
                weather_cur.name = doc["name"];//City
               
                if(scr!=NULL)
                {
                    weather_draw();
                }
                 

        }
    }
    else 
    {
        Serial.println("Error on HTTP request");
    }

    http.end(); //Free the resources

}

void weather_draw(void)
{
     
    char buffer[50]="";
    struct tm *p;
    //EINK
    // eink.setTextColor(GxEPD_BLACK);
    // eink.setFullWindow();
    // eink.fillScreen(GxEPD_WHITE);       
    // eink.display(false);
    // delay(3000);

     
    lv_img_set_src(img,iconIdToImage(weather_cur.weather_icon0,128));
    lv_obj_align(img,scr,LV_ALIGN_IN_TOP_MID,0,40);

    snprintf(buffer,20,"%.1f",weather_cur.main_temp );
    lv_label_set_text(label_temper, buffer); 
    lv_obj_align(label_temper,img,LV_ALIGN_OUT_BOTTOM_LEFT,0,25);

    lv_label_set_text(label_main, weather_cur.weather_description0); 
    lv_obj_align(label_main,img,LV_ALIGN_OUT_BOTTOM_RIGHT,10,10);

    lv_label_set_text(label_name,  weather_cur.name);
     
    lv_obj_align(label_name,label_main,LV_ALIGN_OUT_BOTTOM_RIGHT,0,0);

    snprintf(buffer,20,"%d%%",weather_cur.main_humidity);
    lv_label_set_text(label_humidity, buffer); 
    lv_obj_align(label_humidity,label_name,LV_ALIGN_OUT_BOTTOM_RIGHT,0,0);

    snprintf(buffer,20,"%.1f-%.1f",weather_cur.main_temp_min ,weather_cur.main_temp_max );
    lv_label_set_text(label_minmax, buffer); 
    lv_obj_align(label_minmax,label_temper,LV_ALIGN_OUT_BOTTOM_LEFT,0,0);

    p=gmtime(&weather_cur.dt);
    strftime(buffer,sizeof(buffer),"Updated\r\t%Y-%m-%d %H:%M:%S",p);

    // snprintf(buffer,20,"%d",dt);
    lv_label_set_text(label_time, buffer); 
    lv_label_set_align(label_time,LV_LABEL_ALIGN_RIGHT)   ;                   
    lv_obj_align(label_time,scr,LV_ALIGN_IN_BOTTOM_MID,0,-10);

 


    eink_flash_ready=false;
    eink_scene_ready=false;
     
}



const void *iconIdToImage(const char *id, int size)
{
	int i;
	for (i = 0; i < sizeof(IconIds)/sizeof(IconIds[0]) ; i++)
	{
		if (strcmp(IconIds[i].id.str,id)==0 )
		{
			switch (size)
			{
			case 64: return IconIds[i].icon64;
			case 96: return IconIds[i].icon96;
			case 128: return IconIds[i].icon128;
			case 192: return IconIds[i].icon192;
			case 256: return IconIds[i].icon256;
			default: return NULL;
			}
		}
	}
	return NULL;
}
 
static void vTimerCallback(xTimerHandle pxTimer)
{
    sync_cnt++;
    Serial.printf("[sync_cnt]:%d\n",sync_cnt);
    task_event_data_t event_data;
  
    event_data.type = MSG_WIFI;
    event_data.wifi.event = WIFI_CONFIG_TRY_CONNECT;
    xQueueSend(g_event_queue_handle,&event_data, portMAX_DELAY);
    Serial.printf("[qeue_cnt]---------------:%d\n",uxQueueMessagesWaiting( g_event_queue_handle )); ;


}

static void btn_back_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(event == LV_EVENT_CLICKED) {

         xTimerDelete( timerhandle_weather, 0 );
        
        lv_obj_t * par = lv_obj_get_parent(btn);
        lv_obj_del(par);
        lv_label_set_text(label_menu,"MENU");
        lv_obj_align(label_menu,scr_tft,LV_ALIGN_CENTER, 0 ,0);

        eink_scene_ready=false;
        eink_flash_ready=false;



    }
}